package org.tlang.type;

import org.tlang.context.Location;
import org.tlang.context.SymbolTable;
import org.tlang.context.TypeTable;

public class ClassType extends Type {
    private static final int IS_ROOT_CLASS = Location.UNKNOWN;
    private final int indexSelf;
    private final int indexSuper;
    private final SymbolTable symbolTable;
    private final TypeTable typeTable;
    private final String name;

    public ClassType(String name, int indexSelf, int indexSuper, SymbolTable symbolTable, TypeTable typeTable) {
        this.name = name;
        this.indexSelf = indexSelf;
        this.indexSuper = indexSuper;
        this.symbolTable = symbolTable;
        this.typeTable = typeTable;
    }

    public SymbolTable fieldSymbolTable() {
        return symbolTable;
    }

    public TypeTable fieldTypeTable() {
        return typeTable;
    }

    public SymbolTable methodSymbolTable() {
        return symbolTable.outer();
    }

    public TypeTable methodTypeTable() {
        return typeTable.outer();
    }

    /**
     * 判断是否与目标类型相同
     *
     * @param type 目标类型
     */
    @Override
    public boolean isTypeOf(Type type) {
        if (!(type instanceof ClassType)) {
            return false;
        }

        ClassType classType = (ClassType) type;
        return this.indexSelf == classType.indexSelf;
    }

    /**
     * 判断是否为目标类型的子类
     *
     * @param type      目标类型
     * @param typeTable 类型表
     */
    @Override
    public boolean isSubTypeOf(Type type, TypeTable typeTable) {
        // 类型相同
        if (isTypeOf(type)) {
            return true;
        }

        // 类型不同，且没有父类
        if (indexSuper == IS_ROOT_CLASS) {
            return false;
        }

        // 递归判断父类是否是目标类型的子类
        Type superType = typeTable.get(0, indexSuper);
        return superType.isSubTypeOf(type, typeTable);
    }

    @Override
    public boolean isClassType() {
        return true;
    }

    @Override
    public String toString() {
        return "Class<" + this.name + ">";
    }
}
